cssprovider: Add recursion checks for @import
authorBenjamin Otte <otte@redhat.com>
Tue, 12 Apr 2011 00:50:25 +0000 (02:50 +0200)
committerBenjamin Otte <otte@redhat.com>
Wed, 18 May 2011 19:58:46 +0000 (21:58 +0200)
This is pretty important, because otherwise recursions cause crashes.
And if you accidentally change your theme to one that crashes on load,
all your gonna SEGV and then on reboot, gdm tries to load the theme...

gtk/gtkcssprovider.c

index 5e0d02f990801abc20408464ec4885ec6df91a63..e785ed58f8aa57ee0977625badc5c4accc492d13 100644 (file)
@@ -1238,6 +1238,23 @@ gtk_css_scanner_get_base_url (GScanner *scanner)
   return priv->base;
 }
 
+static gboolean
+gtk_css_scanner_would_recurse (GScanner *scanner,
+                               GFile    *file)
+{
+  while (scanner)
+    {
+      GtkCssScannerPrivate *priv = scanner->user_data;
+
+      if (priv->file && g_file_equal (priv->file, file))
+        return TRUE;
+
+      scanner = priv->parent;
+    }
+
+  return FALSE;
+}
+
 static void
 gtk_css_provider_init (GtkCssProvider *css_provider)
 {
@@ -2282,12 +2299,25 @@ parse_rule (GtkCssProvider  *css_provider,
               return ';';
             }
 
-          /* FIXME: Avoid recursive importing */
-          gtk_css_provider_load_internal (css_provider,
-                                          scanner,
-                                          actual,
-                                          NULL, 0,
-                                          NULL);
+          if (gtk_css_scanner_would_recurse (scanner, actual))
+            {
+              char *path = g_file_get_path (actual);
+              gtk_css_provider_error (css_provider,
+                                      scanner,
+                                      GTK_CSS_PROVIDER_ERROR,
+                                      GTK_CSS_PROVIDER_ERROR_IMPORT,
+                                      "Loading '%s' would recurse",
+                                      path);
+              g_free (path);
+            }
+          else
+            {
+              gtk_css_provider_load_internal (css_provider,
+                                              scanner,
+                                              actual,
+                                              NULL, 0,
+                                              NULL);
+            }
 
           g_object_unref (actual);